package cn.usbtg.session.impl;

import cn.usbtg.session.BTGSession;
import cn.usbtg.session.BTGSessionContext;

import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * BTGSession标准实现类
 */
public class BTGStandardSession implements BTGSession, Serializable {
    private static final long serialVersionUID = 1L;

    private String sessionId; //唯一标识id
    private long creationTime; //创建时间
    private long lastAccessedTime; //最后激活时间
    private int maxInactiveInterval; //最大空闲时间，即session的失效时间
    private boolean isNew;//是否新的session

    private Hashtable<String, Object> attributes; //session存放值的容器

    private long lastUpdateMillis = System.currentTimeMillis(); //上次session访问时间同步更新时间戳

    /**
     * 构造方法，初始化session并设置默认值
     *
     * @param sessionId           String
     * @param maxInactiveInterval long
     */
    public BTGStandardSession(String sessionId, int maxInactiveInterval) {
        this.sessionId = sessionId;
        this.creationTime = System.currentTimeMillis();
        this.lastAccessedTime = System.currentTimeMillis();
        this.maxInactiveInterval = maxInactiveInterval;
        this.isNew = true;

        this.attributes = new Hashtable<>();
    }

    @Override
    public String getId() {
        return this.sessionId;
    }

    @Override
    public long getCreationTime() {
        return this.creationTime;
    }

    @Override
    public long getLastAccessedTime() {
        return this.lastAccessedTime;
    }

    @Override
    public void setLastAccessedTime(long lastAccessedTime) {
        this.lastAccessedTime = lastAccessedTime;
    }

    @Override
    public int getMaxInactiveInterval() {
        return this.maxInactiveInterval;
    }

    @Override
    public void setMaxInactiveInterval(int maxInactiveInterval) {
        this.maxInactiveInterval = maxInactiveInterval;
    }

    @Override
    public boolean isNew() {
        return this.isNew;
    }

    @Override
    public void invalidate() {
        this.maxInactiveInterval = 0;
        BTGStandardSessionContext.getSessionContext().refreshSession(this);
    }

    @Override
    public boolean isInvalidate() {
        return this.lastAccessedTime + this.maxInactiveInterval < System.currentTimeMillis();
    }

    @Override
    public void active() {
        this.lastAccessedTime = System.currentTimeMillis();
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        return this.attributes.keys();
    }

    @Override
    public Object getAttribute(String key) {
        return this.attributes.get(key);
    }

    @Override
    public void setAttribute(String key, Object obj) {
        this.attributes.put(key, obj);
        BTGStandardSessionContext.getSessionContext().refreshSession(this);
    }

    @Override
    public void removeAttribute(String key) {
        this.attributes.remove(key);
        BTGStandardSessionContext.getSessionContext().refreshSession(this);
    }

    @Override
    public BTGSessionContext getSessionContext() {
        return BTGStandardSessionContext.getSessionContext();
    }

    @Override
    public BTGStandardSession cloneMe() {
        BTGStandardSession cloneObj = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            cloneObj = (BTGStandardSession) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return cloneObj;
    }

    @Override
    public void addAttributeNotRefresh(String key, Object obj) {
        this.attributes.put(key, obj);
    }

    @Override
    public long getLastUpdateMillis() {
        return lastUpdateMillis;
    }

    @Override
    public void setLastUpdateMillis(long lastUpdateMillis) {
        this.lastUpdateMillis = lastUpdateMillis;
    }
}